<script setup lang="ts">
import {nextTick, onBeforeUnmount, onMounted, ref, watch} from 'vue'
import PinyinMatch from 'pinyin-match'
import {ElMessage} from 'element-plus'
import keymaster from 'keymaster'

const props = defineProps<{ viewElements: Map<string, HTMLElement> }>()

const searchKey = ref('')
const searchInputVisible = ref(false)
// 用于显示输入框时获取焦点
const searchInput = ref()

// 绑定快捷键打开搜索框
onMounted(() => {
  keymaster('f', () => {
    if (searchInputVisible.value) return true
    searchInputVisible.value = true
    nextTick(() => {
      searchInput.value.focus()
    })
    return false
  })
})
onBeforeUnmount(() => {
  keymaster.unbind('ctrl+f')
})

// 输入的内容变化时显示元素到屏幕中间
watch(searchKey, (newKey) => {
  if (!newKey) return

  setTimeout(() => {
    viewSearchResultElement(newKey)
  }, 1000)
})

function viewSearchResultElement(newKey: string) {
  if (newKey !== searchKey.value) return

  // 先把旧的高亮文本恢复
  restorePreNameDiv()

  // 查找匹配的html元素
  let match: [number, number] | boolean
  let viewElementsArray: [string, HTMLElement]

  for (let entry of props.viewElements.entries()) {
    match = PinyinMatch.match(entry[0], newKey)
    if (match) {
      viewElementsArray = entry
      break
    }
  }
  if (!match) return ElMessage({
      message: `${newKey} = no result`,
      type: 'error',
    })

  // 把匹配的html元素显示到屏幕中间
  const viewItem = viewElementsArray[1]
  // console.log(viewItem)
  viewItem.scrollIntoView({
    behavior: 'smooth',
    block: 'center',
  })

  // 高亮匹配的文本
  highlightMatchStr(viewElementsArray[0], match, viewItem)
}

let preNameText = ''
let preNameDiv: Element = null

function restorePreNameDiv(cleanPreNameDiv = false) {
  if (!preNameDiv) return
  preNameDiv.innerHTML = preNameText
  if (cleanPreNameDiv) {
    preNameDiv = null
  }
}

function highlightMatchStr(emName: string, match: [number, number] | boolean, viewItem: HTMLElement) {
  const prefix = emName.substring(0, match[0])
  const matchStr = emName.substring(match[0], match[1] + 1)
  const suffix = emName.substring(match[1] + 1, emName.length)
  preNameDiv = viewItem.querySelector<Element>('.text')
  preNameDiv.innerHTML = `${prefix}<span style="color: red;font-size: 20px;">${matchStr}</span>${suffix}`
  preNameText = emName
}

// 隐藏输入框
function hiddenSearchInput(toTop = false) {
  cleanInput()
  searchInputVisible.value = false
  if (toTop) {
    document.documentElement.scrollTop = 0
  }
}

// 清空输入框内容
function cleanInput() {
  if (searchKey.value) {
    searchKey.value = ''
    restorePreNameDiv(true)
  }
}
</script>

<template>
  <el-input class="searchInput"
            ref="searchInput"
            v-if="searchInputVisible"
            v-model="searchKey"
            @blur.native.capture="hiddenSearchInput()"
            @keyup.esc="hiddenSearchInput()"
            @keyup.space="cleanInput"
            @keyup.enter="hiddenSearchInput(true)"
            clearable placeholder="name"/>
</template>

<style scoped lang="stylus">
.searchInput
  width 200px
  position: fixed
  top: 250px
  left: 45%
  z-index: 100
</style>